EventBridge と Lambda 関数を利用して、EC2 の停止/削除時に EBS スナップショットを自動取得してみた
はじめに
テクニカルサポートの 片方 です。
EC2 インスタンスを意図せず「削除」又は「停止」していた際に、自動で EC2 インスタンスにアタッチしていた EBS(ルートボリューム含む)のスナップショットを取得するカスタムソリューションを実装してみました。
大まかな流れは以下です。
- EventBridge で EC2 インスタンスの状態変化を監視します。
- "stopping" 又は、"shutting-down" 状態になった場合、Lambda 関数を呼び出します。
- 全ての EBS のスナップショットを取得します。
なお、Lambda 関数を実装せずとも、オートメーションランブックの "AWS-CreateSnapshot" を呼び出せばよいのではと思うかもしれません。
しかしながら、当該ランブックでは複数の EBS を対象に実行できないため、複数の EBS に対応可能な(スナップショット取得) Lambda 関数を作成しました。
実装してみた
以下の順番で実装します。
- 実行ロール
- Lambda 関数
- EventBridge
実行ロール
※ 信頼関係
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
アタッチするポリシー例
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeSnapshots",
"ec2:DescribeVolumes",
"ec2:CreateSnapshot",
"ec2:CreateVolume",
"ec2:AttachVolume",
"ec2:DetachVolume",
"ec2:DeleteVolume"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:<region>:<account-id>:*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:<region>:<account-id>:log-group:/aws/lambda/<function-name>:*"
]
}
]
}
※ 適宜修正してください。
Lambada 関数
Python 3.12 で作成しました。
実行ロールでは、既存のロールを使用するを選択し、先ほど作成したロールを指定します。
実装する Lambda 関数例
import boto3
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
# イベントの内容に基づいて、EC2インスタンスIDを取得
instance_id = event['detail']['instance-id']
print(f"EC2 Instance ID: {instance_id} is stopping. Creating snapshots...")
# EC2インスタンスにアタッチされているEBSボリュームを取得
volumes = ec2.describe_volumes(
Filters=[{
'Name': 'attachment.instance-id',
'Values': [instance_id]
}]
)
# それぞれのボリュームのスナップショットを作成
for volume in volumes['Volumes']:
volume_id = volume['VolumeId']
print(f"Creating snapshot for Volume ID: {volume_id}")
snapshot = ec2.create_snapshot(
VolumeId=volume_id,
Description=f"Snapshot of {volume_id} from instance {instance_id}"
)
print(f"Snapshot created: {snapshot['SnapshotId']}")
return {
'statusCode': 200,
'body': 'Snapshots created successfully.'
}
※ 適宜修正してください。
EventBridge
EventBridge のマネジメントコンソール画面より、左ペインのルールを選択し、「ルールを作成」をクリックします。
EventBridge の名前を入力し、「イベントパターンを持つルール」を選択します。
下部へスクロールを行い、作成のメソッドを「パターンフォームを使用する」を選択します。
イベントパターンのセクションで、以下の設定を行います。
- イベントソース: AWS のサービス
- AWS のサービス: EC2
- イベントタイプ: EC2 Instance State-change Notification
- イベントタイプの仕様 1: 特定の状態
- 特定の状態: shutting-down , stopping
ターゲットを選択において、以下の設定を行います。
- ターゲットタイプ: AWS のサービス
- ターゲットを選択: Lambda 関数
- 関数: 前途で作成した Lambda 関数を指定
後は、そのまま進めて「ルールの作成」を行えば全ての実装は終了です。
検証してみた
EC2 インスタンスを起動させて適当な EBS を複数アタッチします。
停止させます。
インスタンスの状態が「停止済み」になったら、スナップショットが取得されているか確認します。
問題なく全ての EBS のスナップショットが取得されていました。
今度は、削除して取得されるか確認します。
インスタンスの状態が「停止済み」になったら、スナップショットが取得されているか確認します。
こちらも、取得できました
成功です!
まとめ
本ブログが誰かの参考になれば幸いです。
参考資料
- AWS-CreateSnapshot - AWS Systems Manager オートメーションランブックリファレンス
- Amazon EventBridge イベントパターン - Amazon EventBridge
- インスタンスのライフサイクル - Amazon Elastic Compute Cloud
- EC2 - Boto3 1.35.14 documentation
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。